package com.lujieni.test.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class Server {

    public static void main(String[] args) throws IOException {

        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.bind(new InetSocketAddress(8081));
        Selector selector = Selector.open();
        SelectionKey register = ssc.register(selector, SelectionKey.OP_ACCEPT);


        while (true) {
            selector.select();
            int size = selector.selectedKeys().size();
            /*
              1: accept event
              1: read event
              if not use iterator.remove(), accept event will be still exist in the iterator
             */
            System.out.println(size);
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()){
                SelectionKey item = iterator.next();
                if (item.isAcceptable()){
                    ServerSocketChannel channel = (ServerSocketChannel)item.channel();
                    SocketChannel socketChannel = channel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ); //socket channel only focus on read event
                }else if(item.isReadable()){
                    SocketChannel channel = (SocketChannel)item.channel();
                    try {
                        ByteBuffer bb = ByteBuffer.allocate(1024);
                        int read = channel.read(bb);
                        if(read == -1){
                            item.cancel();
                        }else{
                            bb.flip();
                            System.out.println(StandardCharsets.UTF_8.decode(bb));
                        }
                    } catch (IOException e) {
                        System.out.println("client close");
                        item.cancel(); // if client close, cancel the key
                    }
                }
               iterator.remove();
            }
        }
    }
}
